"""
进度对话框组件 - 完整修复版本
"""

import tkinter as tk
from tkinter import ttk
from typing import Optional, Callable
import threading
import time


class ProgressDialog:
    """进度对话框 - 完整修复版本"""

    def __init__(self, parent, title: str = "处理中", message: str = "请稍候..."):
        self.parent = parent
        self.title = title
        self.message = message
        self.is_cancelled = False
        self.progress_value = 0
        self.progress_max = 100

        # 创建对话框
        self.dialog = tk.Toplevel(parent)
        self.dialog.title(title)
        self.dialog.geometry("400x150")
        self.dialog.resizable(False, False)
        self.dialog.transient(parent)
        self.dialog.grab_set()

        # 设置对话框位置（居中）
        self.dialog.update_idletasks()
        x = parent.winfo_x() + (parent.winfo_width() - self.dialog.winfo_width()) // 2
        y = parent.winfo_y() + (parent.winfo_height() - self.dialog.winfo_height()) // 2
        self.dialog.geometry(f"+{x}+{y}")

        # 创建界面
        self.create_widgets()

        # 绑定事件
        self.bind_events()

    def create_widgets(self):
        """创建界面组件"""
        # 主框架
        main_frame = ttk.Frame(self.dialog, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 消息标签
        self.message_var = tk.StringVar(value=self.message)
        message_label = ttk.Label(
            main_frame,
            textvariable=self.message_var,
            justify=tk.CENTER
        )
        message_label.pack(fill=tk.X, pady=(0, 10))

        # 进度条
        self.progress_bar = ttk.Progressbar(
            main_frame,
            orient=tk.HORIZONTAL,
            length=300,
            mode='determinate'
        )
        self.progress_bar.pack(fill=tk.X, pady=(0, 10))

        # 进度文本
        self.progress_text_var = tk.StringVar(value="0%")
        progress_label = ttk.Label(
            main_frame,
            textvariable=self.progress_text_var,
            justify=tk.CENTER
        )
        progress_label.pack(fill=tk.X, pady=(0, 10))

        # 取消按钮
        self.cancel_button = ttk.Button(
            main_frame,
            text="取消",
            command=self.cancel
        )
        self.cancel_button.pack()

    def bind_events(self):
        """绑定事件"""
        self.dialog.protocol("WM_DELETE_WINDOW", self.cancel)
        self.dialog.bind('<Escape>', lambda e: self.cancel())

    def set_message(self, message: str):
        """设置消息文本"""
        self.dialog.after(0, lambda: self.message_var.set(message))

    def set_progress(self, value: int, max_value: int = 100):
        """设置进度"""
        self.dialog.after(0, lambda: self._update_progress(value, max_value))

    def _update_progress(self, value: int, max_value: int):
        """更新进度（线程安全）"""
        self.progress_value = value
        self.progress_max = max_value

        # 更新进度条
        self.progress_bar['maximum'] = max_value
        self.progress_bar['value'] = value

        # 更新进度文本
        if max_value > 0:
            percentage = int((value / max_value) * 100)
            self.progress_text_var.set(f"{percentage}% ({value}/{max_value})")
        else:
            self.progress_text_var.set(f"{value}")

    def set_indeterminate(self, indeterminate: bool = True):
        """设置是否为不确定进度"""
        mode = 'indeterminate' if indeterminate else 'determinate'
        self.dialog.after(0, lambda: self.progress_bar.config(mode=mode))

        if indeterminate:
            self.dialog.after(0, self.progress_bar.start)
        else:
            self.dialog.after(0, self.progress_bar.stop)

    def cancel(self):
        """取消操作"""
        self.is_cancelled = True
        self.dialog.destroy()

    def wait_for_completion(self, task_func: Callable, *args, **kwargs) -> bool:
        """等待任务完成"""
        result = [None]
        exception = [None]

        def run_task():
            try:
                result[0] = task_func(*args, **kwargs)
            except Exception as e:
                exception[0] = e

        # 启动任务线程
        task_thread = threading.Thread(target=run_task, daemon=True)
        task_thread.start()

        # 等待任务完成或取消
        try:
            while task_thread.is_alive() and not self.is_cancelled:
                self.dialog.update()
                time.sleep(0.1)

            if self.is_cancelled:
                return False

            if exception[0]:
                raise exception[0]

            return True

        finally:
            self.dialog.destroy()

    def show(self):
        """显示对话框"""
        return self.dialog


class IndeterminateProgressDialog(ProgressDialog):
    """不确定进度对话框"""

    def __init__(self, parent, title: str = "处理中", message: str = "请稍候..."):
        super().__init__(parent, title, message)
        self.set_indeterminate(True)


class DeterminateProgressDialog(ProgressDialog):
    """确定进度对话框"""

    def __init__(self, parent, title: str = "处理中", message: str = "请稍候..."):
        super().__init__(parent, title, message)
        self.set_indeterminate(False)


def show_progress_dialog(parent, task_func: Callable, *args,
                         title: str = "处理中",
                         message: str = "请稍候...",
                         **kwargs) -> bool:
    """
    显示进度对话框并执行任务

    Args:
        parent: 父窗口
        task_func: 要执行的任务函数
        title: 对话框标题
        message: 初始消息
        *args, **kwargs: 传递给任务函数的参数

    Returns:
        bool: 任务是否成功完成（未被取消）
    """
    dialog = ProgressDialog(parent, title, message)
    return dialog.wait_for_completion(task_func, *args, **kwargs)